local timerfd = require "cauchy.timerfd"
local socket = require "cauchy.socket"
local eventfd = require "cauchy.eventfd"
local epoll = require "cauchy.epoll"
require "os"

--[[
local tfd, err = timerfd.create()
local err = timerfd.settime(tfd, 1000) -- 1000ms == 1s 
-- 创建、设置定时器

local ID = 1

local function worker() 
    print("当前时间：" .. os.date("%Y-%m-%d %H:%M:%S", os.time()))
    local sockfd = socket.connect("121.43.118.7", 8001)

    local s = string.format("register %s %d %d\r\n", string.char(math.random(1, 52) + 64), 1, ID)
    socket.send(sockfd, s)

    ID = ID + 1
    socket.close(sockfd)
end

while true do 
    if timerfd.read(tfd) then 
        worker()
    end
end 

local err = timerfd.close(tfd) 

--]]



--[[
local cauchy = require "lualib.time"

-- "Gateway": "172.17.0.1",
-- "IPAddress": "172.17.0.2",

-- 要从外部连入，需要同样映射端口 8001:8001
local listener = socket.listen("0.0.0.0", 8001)

while true do 
    local fd, ip_port = socket.accept(listener)
    print(fd, ip_port)
end 

close(listener)
]]

local connects = {}
local coroutines = {}

function disconnect(epfd, fd) 
    epoll.unregister(epfd, fd) 
    connects[fd] = nil 
    coroutines[fd] = nil 
    socket.close(fd)
end 

function coroutine_create(epfd, fd)
    local co = coroutine.create(function()
        while true do 
            local data, err = socket.recv(fd)
            if data and #data > 0 then 
                    io.write("recv from [ " .. fd .. " ]" .. " : " .. data) 
                socket.send(fd, data)
            else
                disconnect(epfd, fd)
                break 
            end 
            
            coroutine.yield()
        end     
    end)
    coroutines[fd] = co 
end 

function accept_connection(epfd, fd) 
    local client, ip_port = socket.accept(fd)
    socket.setnonblocking(client)
    connects[client] = client

        print("accept from " .. "[ " .. ip_port .. " ]", "client = " .. client)

    epoll.register(epfd, client, epoll.EPOLLIN)

    coroutine_create(epfd, client)
end 

function coroutine_handler(fd)
    local client = connects[fd] 
    local co = coroutines[fd]
    if coroutine.status(co) == "suspended" then 
        coroutine.resume(co)
    end 
end 

function start_server()
    epfd = epoll.create() 
    listener = socket.listen("0.0.0.0", 8001)
    socket.setnonblocking(listener)

        print("create listen: ", listener)

    epoll.register(epfd, listener, epoll.EPOLLIN)

    while true do 
        local events = epoll.wait(epfd, -1, 1024) 

        for fd, event in pairs(events) do 
            if fd == listener then  -- accept socket
                accept_connection(epfd, fd)
            elseif event & epoll.EPOLLIN ~= 0 then  -- coroutine  
                coroutine_handler(fd)
            elseif event & epoll.EPOLLHUP ~= 0 then -- disconnect 
                disconnect(epfd, fd)
            end 
        end 
    end 
end

function main() 
    start_server()
end 
main()